home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
PASCAL
/
0187.ZIP
/
LANDER.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-01-20
|
9KB
|
409 lines
program lander;
const
instrfile = 'LANDINST.DAT';
maxrand = 32767;
timeinc = 0.1;
slightly = 0.1;
moderately = 0.2;
very = 0.3;
impossible = 0.5;
certainty = 1.0;
minmeteors = 2.0;
maxmeteors = 7.0;
eachmisschance = 0.8;
minavoid = 10;
landingheight = 0.1;
crashlandspeed = 6.0;
type
answers = set of 'A'..'Z';
str80 = string[80];
var
speed, height, gravity : real;
maxlandingspeed : real;
chance, misschance : real;
burn, fuel : integer;
nummeteors : integer;
inp : string[10];
ranout : boolean;
(*
* returns a random real number between lowlimit and highlimit
*)
function rand(lowlimit, highlimit : real) : real;
begin
rand := lowlimit + (highlimit - lowlimit + 1) * random;
end;
(*
* returns true if a random number, weighted by the difficulty level, is
* less than the argument
*)
function unlucky(percentchance : real) : boolean;
begin
unlucky := rand(0.0, 1.0 - chance) <= percentchance;
end;
(*
* converts a numerical ascii character to its corresponding integral value
*)
function asciitoint(digit : char) : integer;
begin
asciitoint := ord(digit) - ord('0');
end;
(*
* returns true if the argument is a numerical digit
*)
function isdigit(ch : char) : boolean;
begin
isdigit := (ch >= '0') and (ch <= '9');
end;
(*
* convert determines the numerical value of the digits ina string. it returns
* the integer and updates the string to now contain whatever was after the
* end of the number. if the string is blank, the value is zero; if a number
* is not found it returns -1.
*)
function convert(numstring : str80) : integer;
var
intvalue : integer;
position : integer;
digitsfound : integer;
endofnumber : boolean;
notinteresting : boolean;
begin
intvalue := 0;
digitsfound := 0;
position := 1;
endofnumber := false;
notinteresting := true;
if length(numstring) > 0 then
begin
while (position < length(numstring)) and notinteresting do
if numstring[position] = ' ' then
position := position + 1
else
notinteresting := false;
while (position <= length(numstring)) and (not endofnumber) do
if isdigit(numstring[position]) then
begin
intvalue := intvalue * 10 + asciitoint(numstring[position]);
position := position + 1;
digitsfound := digitsfound + 1;
end
else
endofnumber := true;
if digitsfound = 0 then
intvalue := -1;
end;
convert := intvalue;
end;
(*
* asks a question with a single character answer. if the response is in the
* set 'answers', the letter is returned. otherwise the string ifbad is
* printed and the question is asked again.
*)
function ask(question, ifbad : str80; responses : answers) : char;
var
bad : boolean;
ch : char;
begin
bad := true;
repeat
write(question);
readln(ch);
writeln;
if ch in responses then
bad := false
else
writeln(ifbad);
until not bad;
ask := ch;
end;
(*
* prints out the instructions from a file instrfile
*)
procedure instructions;
var
instruct : text;
ch : char;
str : string[80];
begin
assign(instruct,instrfile);
reset(instruct);
while not eof(instruct) do
begin
readln(instruct,str);
writeln(str);
end;
end;
procedure startup;
begin
if ask('Do you want instructions? ','Please answer Y or N',['Y','N']) = 'Y' then
instructions;
randomize;
end;
(*
* ask the player for the difficulty level of the next landing
*)
procedure getdifficulty;
var
level : char;
begin
level := ask('Level of difficulty? ','B:Beginner, E:Expert, N:Navigator, A:Astronaut',
['B','E','N','A']);
case level of
'B' : chance := slightly;
'E' : chance := moderately;
'N' : chance := very;
'A' : chance := impossible;
end;
end;
(*
* variables that must be re-set each time a new landing is attempted
*)
procedure startgame;
begin
getdifficulty;
gravity := rand(9.0 + chance, 11.0 + chance);
height := rand(1.0 + chance, 2.0 + chance) * 100.0;
speed := rand(0.0, 100.0 * chance) + 30.0;
fuel := round(50.0 * rand(3.0 - chance, 4.0 - chance));
maxlandingspeed := crashlandspeed - 10.0 * chance;
misschance := certainty;
ranout := false;
end;
(*
* tell player his height, speed and direction
*)
procedure writestatus;
begin
writeln;
write('You are ');
if speed > 0.0 then
write('falling')
else
write('rising');
writeln(' from a height of ',height:1:1);
writeln('meters at ',abs(speed):1:1,' m/s.');
if not ranout then
writeln('There are ',fuel:1,' liters of fuel left.');
ranout := fuel = 0;
end;
(*
* determines if there are any meteors, and if so, how many
*)
procedure lookformeteors;
var
eachrock : integer;
begin
misschance := certainty;
if unlucky(0.1) then
begin
nummeteors := round(rand(minmeteors,maxmeteors + 10.0 * chance));
for eachrock := 1 to nummeteors do
misschance := misschance * eachmisschance;
writeln('We are on a collision course with ',nummeteors:1);
write('meteors.');
if ranout then
writeln
else
begin
writeln('If we do not use more than ',minavoid:1,'liters of fuel in the');
writeln('next second, there is a ',round(100.0*(1.0-misschance)),
' % probability that we will be');
writeln('hit. If more is used it will be only 10 %.');
end;
end;
end;
(*
* asks the player for the amount of fuel to use in the next time period.
*)
procedure getburn;
const
fuelprompt = 'Units of fuel : ';
begin
repeat
write(fuelprompt);
readln(inp);
burn := convert(inp);
if burn > fuel then
writeln('There isn''t that much fuel left.')
else if burn < 0 then
writeln('I don''t think that''s possible.');
until (burn <= fuel) and (burn >= 0);
end;
(*
* figure out the craft's new speed according to the laws of physics
*)
procedure updatestatus;
var
deltat : integer;
begin
fuel := fuel - burn;
deltat := 0;
repeat
deltat := deltat + 1;
height := height - speed * timeinc - (gravity - burn) * 0.5 * sqr(timeinc);
speed := speed + (gravity - burn) * timeinc;
until (deltat = trunc(1 / timeinc)) or (height <= landingheight);
end;
(*
* all the procedures that make a turn
*)
procedure doaturn;
begin
writestatus;
lookformeteors;
if fuel > 0 then
getburn
else
burn := 0;
updatestatus;
end;
(*
* the course has changed: meteors have a lower chance of hitting
*)
function coursechanged : boolean;
begin
if unlucky(0.1) then
begin
writeln('Despite the precautionary measures taken, the ship was destroyed.');
coursechanged := true;
end
else
begin
writeln('Your prudent actions saved the ship from the menacing meteors!');
coursechanged := false;
end
end;
function coursesame: boolean;
begin
if not unlucky(1.0 - misschance) then
begin
writeln('Your piloting skills have steered you through the center of the swarm!');
coursesame := false;
end
else if ranout then
begin
writeln('What a pity .. your craft was demolished by meteors before it could');
writeln('be vaporized on contact with the surface.');
coursesame := true;
end
else
begin
writeln('Your pointless gambling has destroyed the ship, you foolish plebe!');
coursesame := true;
end;
end;
(*
* figures if any meteors (if there were any) managed to hit the ship.
* different messages are printed depending on the thrust of the last turn.
*)
function anyhit : boolean;
begin
if (misschance = certainty) or (height <= landingheight) then
anyhit := false
else if burn > minavoid then
anyhit := coursechanged
else
anyhit := coursesame;
end;
(*
* returns true if the ship has come close enough to the ground that we can
* say it has landed. could crash or touch down safely.
*)
function landed : boolean;
begin
if height < landingheight then
begin
speed := abs(speed);
if speed < maxlandingspeed then
write('We have landed safely')
else
write('We have crashed');
writeln(' at a speed of ',speed:1:1,' meters/second.');
landed := true;
end
else
landed := false;
end;
begin
startup;
repeat
startgame;
repeat
doaturn;
until landed or anyhit;
until ask('Again? ','Y or N',['Y','N']) = 'N';
writeln('Bye!');
end.